/********************************************************************/
/*  Copyright (C) School of Software Engineering of USTC, 2012                               
/*                                                                                                                       
/*  FILE NAME: socketwrapper.c                                                                                          
/*  PRINCIPAL AUTHOR: SA12226114(Xin Zhu), SA12226139(Dan Shu)                    
/*  SUBSYSTEM NAME: DB                                                                                    
/*  MODULE NAME: sw                                                                                    
/*  LANGUAGE: C                                                                                                 
/*  TARGET ENVIRONMENT: Linux                                                                          
/*  DATE OF FIRST RELEASE: 2012-12-20                                                             
/*  DESCRIPTION: Impement of Abstract Interface for Tokyo Cabinet DB API              
/********************************************************************/


#include "socketwrapper.h"

int sw_gen_connection()
{



}


/*****************************************************************
Function Name: 
Description: 
Parameter:  

@type: TCP (SOCK_STREAM) / UDP (SOCK_DGRAM)

Author: SA12226114(Xin Zhu), SA12226139(Dan Shu)
Date: 2012-12-20
******************************************************************/
int sw_create_socket(int af, int type, int protocol)
{
    int socketfd;
    
    if((socketfd = socket(af, type, protocol)) == -1)
    {
        printf("create socket error: %s(errno: %d)\n", strerror(errno), errno);
        
        return LILY_FALSE;
    }

    return socketfd;
}


/*****************************************************************
Function Name: 
Description: 
Parameter:  
Author: SA12226114(Xin Zhu), SA12226139(Dan Shu)
Date: 2012-12-20
******************************************************************/
int sw_init_socket(struct sockaddr_in *psockaddress, int length, char *pipaddr)
{
    memset(psockaddress, 0, length);
    psockaddress->sin_family = AF_INET;
    psockaddress->sin_port = htons(10000);

    if(inet_pton(AF_INET, pipaddr, &(psockaddress->sin_addr)) <= 0)
    {
        printf("inet_pton error for %s\n", pipaddr);
        
        return LILY_FALSE;
    }

    return LILY_TRUE;
}


/*****************************************************************
Function Name: 
Description: 
Parameter:  
Author: SA12226114(Xin Zhu), SA12226139(Dan Shu)
Date: 2012-12-20
******************************************************************/
void sw_init_socket2(struct sockaddr_in *psockaddress, int length)
{
    memset(psockaddress, 0, length);
    psockaddress->sin_family = AF_INET;
    //psockaddress->sin_addr.s_addr = htonl(INADDR_ANY);
    psockaddress->sin_addr.s_addr = INADDR_ANY;
    psockaddress->sin_port = htons(10000);

    return;   
}


/*****************************************************************
Function Name: 
Description: 
Parameter:  
Author: SA12226114(Xin Zhu), SA12226139(Dan Shu)
Date: 2012-12-20
******************************************************************/
int sw_bind(int sockfd, struct sockaddr* psockaddr, int length)
{
    if(bind(sockfd, psockaddr, length) == -1)
    {
        printf("bind socket error: %s(errno: %d)\n", strerror(errno), errno);
        
        return LILY_FALSE;
    }

    return LILY_TRUE;
}


/*****************************************************************
Function Name: 
Description: 
Parameter:  
Author: SA12226114(Xin Zhu), SA12226139(Dan Shu)
Date: 2012-12-20
******************************************************************/
int sw_listen(int sockfd, int numoflisten)
{
    if(listen(sockfd, numoflisten) == -1)
    {
        printf("listen socket error: %s(errno: %d)\n",strerror(errno),errno);
        
        return LILY_FALSE;
    }

    return LILY_TRUE;
}


/*****************************************************************
Function Name: 
Description: 
Parameter:  
Author: SA12226114(Xin Zhu), SA12226139(Dan Shu)
Date: 2012-12-20
******************************************************************/
int sw_accept(int listenfd)
{   
    int connfd;
    
    if((connfd = accept(listenfd, (struct sockaddr *)NULL, NULL)) == -1)
    {
       printf("accept socket error: %s(errno: %d)", strerror(errno), errno);
       
       return 0;
    }

    return connfd;
}


/*****************************************************************
Function Name: 
Description: 
Parameter:  
Author: SA12226114(Xin Zhu), SA12226139(Dan Shu)
Date: 2012-12-20
******************************************************************/
int sw_connect(int sockfd, struct sockaddr *psockaddress, int length)
{
    if(connect(sockfd, psockaddress, length) < 0)
    {
        printf("connect error: %s(errno: %d)\n",strerror(errno), errno);
        
        return LILY_FALSE;
    }

    return LILY_TRUE;
}


/*****************************************************************
Function Name: 
Description: 
Parameter:  
Author: SA12226114(Xin Zhu), SA12226139(Dan Shu)
Date: 2012-12-20
******************************************************************/
int sw_send(int sockfd, char* buf, int length, int flags)
{   
    if(send(sockfd, buf, length, flags) < 0)
    {
        printf("send msg error: %s(errno: %d)\n", strerror(errno), errno);
        
        return LILY_FALSE;
    }

    return LILY_TRUE;
}


/*****************************************************************
Function Name: 
Description: 
Parameter:  
Author: SA12226114(Xin Zhu), SA12226139(Dan Shu)
Date: 2012-12-20
******************************************************************/
int sw_recv(int sockfd, char* buf, int length, int flags)
{
    int bytes_rev;
    
    bytes_rev = recv(sockfd, buf, length, flags);

    return bytes_rev;
}


/*****************************************************************
Function Name: 
Description: 
Parameter:  
Author: SA12226114(Xin Zhu), SA12226139(Dan Shu)
Date: 2012-12-20
******************************************************************/
void sw_close(int sockfd)
{
    close(sockfd);

    return;
}


/*****************************************************************
Function Name: sw_make_socket_non_blocking
Description: make the socket non blocking.
Parameter:  
Author: SA12226114(Xin Zhu), SA12226139(Dan Shu)
Date: 2012-12-20
******************************************************************/
void sw_make_socket_non_blocking(int sockfd)
{
    int opts;

    /* get current attribute of socket */
    if(fcntl(sockfd, F_GETFL) < 0)
    {
        perror("fcntl(sock,GETFL)");

        return;
    }

    /* add non blocking attribute */
    opts = opts|O_NONBLOCK;
    if(fcntl(sockfd, F_SETFL, opts) < 0)
    {
        perror("fcntl(sock,SETFL,opts)");

        return;
    }

    return;
}


/*****************************************************************
Function Name: main
Description:
Parameter:  

@argc: argument count
@argv: argument vector

Author: 
Date:  
******************************************************************/
int sw_get_host_ip(char *argv, char *result)
{
    char   *ptr, **pptr;
    struct hostent *hptr;
    char   str[32];
    ptr = argv;

    if((hptr = gethostbyname(ptr)) == NULL)
    {
        printf(" gethostbyname error for host:%s\n", ptr);
        
        return 0; 
    }

    printf("official hostname:%s\n",hptr->h_name);
    for(pptr = hptr->h_aliases; *pptr != NULL; pptr++)
        printf(" alias:%s\n",*pptr);

    switch(hptr->h_addrtype)
    {
        case AF_INET:
        case AF_INET6:
            pptr=hptr->h_addr_list;
            for(; *pptr!=NULL; pptr++)
            {
                printf(" address:%s\n", inet_ntop(hptr->h_addrtype, *pptr, str, sizeof(str)));
            }
            printf(" first address: %s\n", inet_ntop(hptr->h_addrtype, hptr->h_addr, str, sizeof(str)));

            strncpy(result, inet_ntop(hptr->h_addrtype, hptr->h_addr, str, sizeof(str)), sizeof(str));
            
            break;
        default:
            printf("unknown address type\n");
        break;
    }

    return 1;
}


/*****************************************************************
Function Name: main
Description:
Parameter:  

@argc: argument count
@argv: argument vector

Author: 
Date:  
******************************************************************/
void sw_connect_server(char *ip, int *sockfd)
{
    struct sockaddr_in servaddr;

    /* generate a new socket for client */
    *sockfd = sw_create_socket(PF_INET, SOCK_STREAM, 0);
    
    /* initialize structure sockaddr_in with protocol family, port number, ip */
    sw_init_socket(&servaddr, sizeof(servaddr), ip);
    
    /* connect server using socket id */
    if(!sw_connect((*sockfd), (struct sockaddr*)&servaddr, sizeof(servaddr)))
    {
        debug_print("sw_connect_server can not connet to server.\n");
        
        return;
    }
    
    return;
}







